package com.fw.ui.view.common.event;

import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Scope;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.stereotype.Component;

import com.fw.ui.ApplicationUI;
import com.fw.ui.bao.CaptchaBAO;
import com.fw.ui.bao.MessageBAO;
import com.fw.ui.core.authentication.AuthenticationUserToken;
import com.fw.ui.util.UICommonUtils;
import com.fw.ui.util.VaadinApplicationObjectSupport;
import com.fw.ui.view.common.CaptchaPanel;
import com.fw.ui.view.common.LoginPanel;
import com.fw.ui.view.event.AbstractButtonClickListener;
import com.vaadin.server.VaadinService;
import com.vaadin.server.VaadinSession;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.TextField;

@Component
@Scope(SCOPE_PROTOTYPE)
public class LoginPanelLoginButtonClickListener extends AbstractButtonClickListener {

    private static final long serialVersionUID = 1L;

    @Autowired
    @Qualifier("authenticationProvider")
    private AuthenticationProvider authenticationProvider;
    @Autowired
    protected transient VaadinApplicationObjectSupport app;
    @Autowired
    private MessageBAO messageBAO;
    @Autowired
    private CaptchaBAO captchaBAO;
    @Autowired
    private UICommonUtils uiCommonUtils;

    @Override
    public Map<String, Object> click(ClickEvent event) throws Exception {
	LoginPanel loginPanel = (LoginPanel) this.getBasedComponent();
	ApplicationUI applicationUI = (ApplicationUI) loginPanel.getUI();
	try {

	    String username = loginPanel.getTxtUsername().getValue();
	    String password = loginPanel.getTxtPassword().getValue();

	    UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);
	    token.setDetails(new WebAuthenticationDetails((HttpServletRequest) VaadinService.getCurrentRequest()));
	    Authentication authentication = authenticationProvider.authenticate(token);
	    if (authentication.isAuthenticated()) {
		uiCommonUtils.clearAllUIComponentWithPrefixDefaultValue(loginPanel, null);
		loginPanel.getCaptchaPanel().setVisible(false);
		SecurityContextHolder.getContext().setAuthentication(authentication);
		loginPanel.getBtnLogin().removeShortcutListener(this.getShortcutListener());
		applicationUI.buildMainView(false);
	    } else {
		uiCommonUtils.clearAllUIComponentNoInputFieldWithPrefix(loginPanel);
		Map<String, Object> map = new HashMap<String, Object>();
		boolean showCaptcha = false;
		if (authentication != null && authentication instanceof AuthenticationUserToken) {
		    AuthenticationUserToken userToken = (AuthenticationUserToken) authentication;
		    if (userToken.getMessageCode() != null) {
			if (userToken.getMessageCode().equals(
				"errors.com.fw.service.bouserauthentication.BOUserAuthenticationService.authenticate.expire")
				|| userToken.getMessageCode().equals(
					"errors.com.fw.service.bouserauthentication.BOUserAuthenticationService.authenticate.forceChange")) {
			    SecurityContextHolder.getContext().setAuthentication(authentication);
			    loginPanel.getBtnLogin().removeShortcutListener(this.getShortcutListener());
			    applicationUI.buildChangePassword();
			    return null;
			} else {
			    map.put(MessageBAO.MESSAGE_WARNING_TYPE, userToken.getMessageCode());
			    uiCommonUtils.clearAllUIComponentNoInputFieldWithPrefix(loginPanel);
			}

			if ("errors.com.fw.service.bouserauthentication.BOUserAuthenticationService.authenticate.invalid".equals(userToken
				.getMessageCode())
				|| "errors.com.fw.service.bouserauthentication.BOUserAuthenticationService.authenticate.forceChange"
					.equals(userToken.getMessageCode())) {
			    showCaptcha = true;
			}
		    }
		}
		if (showCaptcha) {
		    loginPanel.getCaptchaPanel().reloadCaptcha();
		    loginPanel.getCaptchaPanel().setVisible(true);
		}
		return map;
	    }
	} catch (AuthenticationException e) {
	    uiCommonUtils.clearAllUIComponentNoInputFieldWithPrefix(loginPanel);
	    Map<String, Object> map = new HashMap<String, Object>();
	    if ("errors.com.fw.service.bouserauthentication.BOUserAuthenticationService.authenticate.expire".equals(e.getMessage())
		    || "errors.com.fw.service.bouserauthentication.BOUserAuthenticationService.authenticate.forceChange".equals(e
			    .getMessage())) {
		applicationUI.buildChangePassword();
		return null;
	    } else {
		loginPanel.getCaptchaPanel().reloadCaptcha();
		loginPanel.getCaptchaPanel().setVisible(true);
		map.put(MessageBAO.MESSAGE_WARNING_TYPE, e.getMessage());
		return map;
	    }
	} catch (Exception e) {
	    uiCommonUtils.clearAllUIComponentNoInputFieldWithPrefix(loginPanel);
	    throw e;
	}
	return null;
    }

    @Override
    public boolean validate(ClickEvent event) throws Exception {
	LoginPanel loginPanel = (LoginPanel) this.getBasedComponent();
	CaptchaPanel captchaPanel = loginPanel.getCaptchaPanel();

	uiCommonUtils.clearAllUIComponentNoInputFieldWithPrefix(loginPanel);
	uiCommonUtils.clearAllUIComponentNoInputFieldWithPrefix(captchaPanel);

	String username = loginPanel.getTxtUsername().getValue();
	String password = loginPanel.getTxtPassword().getValue();

	boolean isCaptchaVisible = captchaPanel.isVisible();
	boolean usernameValid = (username != null && username.trim().length() > 0);
	boolean passwordValid = (password != null && password.trim().length() > 0);
	boolean captChaValid = false;

	if (isCaptchaVisible) {
	    TextField txtText = captchaPanel.getTxtCaptchaText();
	    String captcha = txtText.getValue();
	    boolean captchaValid = (captcha != null && captcha.trim().length() > 0);
	    if (!captchaValid) {
		txtText.addStyleName("v-textfield-error");
		captchaPanel.getLblTextValidateMessage().setValue(
			this.messageBAO.getMessage("com.fw.ui.view.common.CaptchaPanel.message.captcha.mandatory"));
		captchaPanel.getRowTextValidate().setVisible(true);
	    } else {
		String sessionId = VaadinSession.getCurrent().getSession().getId();
		Boolean isCaptchaValid = captchaBAO.validateCaptcha(sessionId, captcha);
		if (isCaptchaValid != null && isCaptchaValid.booleanValue()) {
		    captChaValid = true;
		} else {
		    captchaPanel.reloadCaptcha();
		    captchaPanel.getTxtCaptchaText().setValue("");
		    captchaPanel.getTxtCaptchaText().focus();
		}
	    }
	} else {
	    captChaValid = true;
	}

	if (usernameValid && passwordValid && captChaValid) {
	    return true;
	} else {
	    if (!usernameValid) {
		loginPanel.getTxtUsername().addStyleName("v-textfield-error");
		loginPanel.getLblUsernameValidateMessage().setValue(
			this.messageBAO.getMessage("com.fw.ui.view.common.LoginPanel.message.username.mandatory"));
		loginPanel.getRow1Validate().setVisible(true);
	    }
	    if (!passwordValid) {
		loginPanel.getTxtPassword().addStyleName("v-textfield-error");
		loginPanel.getLblPasswordValidateMessage().setValue(
			this.messageBAO.getMessage("com.fw.ui.view.common.LoginPanel.message.password.mandatory"));
		loginPanel.getRow2Validate().setVisible(true);
	    }
	    if (!captChaValid) {
		captchaPanel.getTxtCaptchaText().addStyleName("v-textfield-error");
		captchaPanel.getLblTextValidateMessage().setValue(
			this.messageBAO.getMessage("com.fw.ui.view.common.CaptchaPanel.message.captcha.invalid"));
		captchaPanel.getRowTextValidate().setVisible(true);
	    }
	}

	return false;
    }
}
